package com.lfy.yunpicture.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lfy.yunpicture.common.ErrorCode;
import com.lfy.yunpicture.constant.UserConstant;
import com.lfy.yunpicture.exception.BusinessException;
import com.lfy.yunpicture.exception.ThrowUtils;
import com.lfy.yunpicture.model.dto.statistics.*;
import com.lfy.yunpicture.model.entity.Picture;
import com.lfy.yunpicture.model.entity.Space;
import com.lfy.yunpicture.model.entity.User;
import com.lfy.yunpicture.model.enums.SpaceLeaveEnum;
import com.lfy.yunpicture.model.vo.statistic.*;
import com.lfy.yunpicture.service.PictureService;
import com.lfy.yunpicture.service.SpaceService;
import com.lfy.yunpicture.service.SpaceStatisticService;
import com.lfy.yunpicture.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SpaceStatisticServiceImpl implements SpaceStatisticService {
    @Resource
    private SpaceService spaceService;
    @Resource
    private PictureService pictureService;
    @Resource
    private UserService userService;

    @Override
    public SpaceSizeUsageResponse getSpaceSizeUsageSituation(SpaceSizeUsageRequest spaceSizeUsageRequest, User user) {
        // 拼接查询条件
        QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
        Space space = buildQueryWrapper(spaceSizeUsageRequest, pictureQueryWrapper, user);
        // 只查询图片的大小与数量
        pictureQueryWrapper.select("sum(picSize) as totalSize", "count(*) as totalNumber");
        // 查询数据库,只查询出我指定查询的字段
        Map<String, Object> map = pictureService.getMap(pictureQueryWrapper);
        SpaceSizeUsageResponse spaceSizeUsageResponse = new SpaceSizeUsageResponse();
        if (CollUtil.isNotEmpty(map)) {
            BigDecimal totalSize = (BigDecimal) map.get("totalSize");
            if(totalSize != null){
                spaceSizeUsageResponse.setTotalSize(totalSize.longValue());
            }
            spaceSizeUsageResponse.setTotalNumber((Long) map.get("totalNumber"));
        }
        if (space != null) {
            spaceSizeUsageResponse.setMaxSize(space.getMaxSize());
            spaceSizeUsageResponse.setMaxNumber(space.getMaxCount());
        }
        return spaceSizeUsageResponse;
    }

    @Override
    public List<SpaceCategoryUsageResponse> getSpaceCategoryUsageSituation(SpaceCategoryUsageRequest spaceSizeUsageRequest, User user) {
        // 拼接查询条件
        QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
        Space space = buildQueryWrapper(spaceSizeUsageRequest, pictureQueryWrapper, user);
        // 只查询出前十的分类与每个分类下的图片数量,并且category不为null
        pictureQueryWrapper.select("category as categoryName,count(*) as categoryUsageNumber")
                .groupBy("categoryName")
                .ne("category", "null")
                .orderByDesc("categoryUsageNumber")
                .last("limit "+spaceSizeUsageRequest.getTop());
        List<Map<String, Object>> maps = pictureService.getBaseMapper().selectMaps(pictureQueryWrapper);
        if (CollUtil.isEmpty(maps)) {
            return null;
        }
        List<SpaceCategoryUsageResponse> collect = maps.stream()
                .map(map -> {
                    SpaceCategoryUsageResponse response = new SpaceCategoryUsageResponse();
                    response.setCategoryName((String) map.get("categoryName")); // 设置分类名称
                    response.setCategoryUsageNumber((Long) map.get("categoryUsageNumber")); // 设置分类下的图片数量
                    return response;
                })
                .collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<SpaceTagUsageResponse> getSpaceTagUsageSituation(SpaceTagUsageRequest spaceSizeUsageRequest, User user) {
        // 拼接查询条件
        QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
        Space space = buildQueryWrapper(spaceSizeUsageRequest, pictureQueryWrapper, user);
        // 查询数据库
        pictureQueryWrapper.select("tags")
                .ne("tags", "null");
        List<Object> objects = pictureService.getBaseMapper()
                .selectObjs(pictureQueryWrapper);
        if (CollUtil.isEmpty(objects)) {
            return null;
        }
        Map<String, Long> collect = objects.stream()
                // 将每个对象中的字符串转换为流
                .flatMap(obj -> {
                    String tags = StrUtil.toString(obj);
                    return JSONUtil.toList(tags, String.class).stream();
                })
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));
        List<SpaceTagUsageResponse> responses = collect.entrySet()
                .stream()
                .map(entry -> {
                    SpaceTagUsageResponse response = new SpaceTagUsageResponse();
                    response.setTagName(entry.getKey());
                    response.setTagUsageNumber(entry.getValue());
                    return response;
                })
                // 降序排列
                .sorted(Comparator.comparingLong(SpaceTagUsageResponse::getTagUsageNumber).reversed())
                .collect(Collectors.toList());
        System.out.println(responses);
        return responses;
    }

    @Override
    public List<SpacePictureSizeRangeResponse> getSpacePictureSizeRangeSituation(SpacePictureSizeRangeRequest spacePictureSizeRangeRequest, User user) {
        // 拼接查询条件
        QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
        Space space = buildQueryWrapper(spacePictureSizeRangeRequest, pictureQueryWrapper, user);
        // 图片大小范围 (<500KB | >500KB && < 1MB | >1MB)
        pictureQueryWrapper.select("case when picSize < 500*1024 then '<500KB' " +
                        "when picSize >= 500*1024 and picSize < 1024*1024 then '500KB-1MB' " +
                        "else '>1MB' end as sizeRangeName" +
                        ",count(*) as pictureNumber")
                .ne("picSize", "null")
                .groupBy("sizeRangeName")
                .orderByDesc("pictureNumber");
        // 查询数据库
        List<Map<String, Object>> maps = pictureService.getBaseMapper()
                .selectMaps(pictureQueryWrapper);
        if (CollUtil.isEmpty(maps)) {
           return null;
        }
        List<SpacePictureSizeRangeResponse> collect = maps.stream()
                .map(map -> {
                    SpacePictureSizeRangeResponse response = new SpacePictureSizeRangeResponse();
                    response.setSizeRangeName((String) map.get("sizeRangeName"));
                    response.setPictureNumber((Long) map.get("pictureNumber"));
                    return response;
                })
                .collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<SpacePictureUploadConditionResponse> getSpacePictureUploadConditionSituation(SpacePictureUploadConditionRequest spacePictureUploadConditionRequest, User user) {
        // 参数校验
        ThrowUtils.throwIf(spacePictureUploadConditionRequest.getUploadCycle() == null, ErrorCode.PARAMS_ERROR);
        Long uploadUserId = spacePictureUploadConditionRequest.getUploadUserId();
        if (ObjectUtil.isNotEmpty(uploadUserId)) {
            User userById = userService.getById(uploadUserId);
            ThrowUtils.throwIf(userById == null, ErrorCode.PARAMS_ERROR, "上传用户不存在");
        }
        // 拼接查询条件
        QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();
        Space space = buildQueryWrapper(spacePictureUploadConditionRequest, pictureQueryWrapper, user);
        pictureQueryWrapper.eq(ObjectUtil.isNotEmpty(uploadUserId), "userId", uploadUserId);
        // 按照日周月统计
        switch (spacePictureUploadConditionRequest.getUploadCycle()) {
            case "day":
                pictureQueryWrapper.select("DATE_FORMAT(createTime,'%Y-%m-%d') as uploadTime,count(*) as uploadNumber")
                        .groupBy("uploadTime");
                break;
            case "week":
                pictureQueryWrapper.select("YEARWEEK(createTime) as uploadTime,count(*) as uploadNumber")
                        .groupBy("uploadTime");
                break;
            case "month":
                pictureQueryWrapper.select("DATE_FORMAT(createTime,'%Y-%m') as uploadTime,count(*) as uploadNumber")
                        .groupBy("uploadTime");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        pictureQueryWrapper.orderByDesc("uploadTime");
        // 查询数据库
        List<Map<String, Object>> maps = pictureService.getBaseMapper()
                .selectMaps(pictureQueryWrapper);
        if (CollUtil.isEmpty(maps)) {
           return null;
        }
        List<SpacePictureUploadConditionResponse> collect = maps.stream()
                .map(map -> {
                    SpacePictureUploadConditionResponse response = new SpacePictureUploadConditionResponse();
                    response.setUploadDate(map.get("uploadTime").toString());
                    response.setUploadNumber((Long) map.get("uploadNumber"));
                    return response;
                })
                .collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<SpaceUsageRankResponse> getSpaceUsageRankSituation(SpaceUsageRankRequest spaceUsageRankRequest, User user) {
        // 校验参数
        ThrowUtils.throwIf(spaceUsageRankRequest.getTop() == null || spaceUsageRankRequest.getTop() < 0, ErrorCode.PARAMS_ERROR);
        Integer spaceLeave = spaceUsageRankRequest.getSpaceLeave();
        if (ObjectUtil.isNotEmpty(spaceLeave)) {
            SpaceLeaveEnum enumBySpaceLeave = SpaceLeaveEnum.getEnumBySpaceLeave(spaceLeave);
            ThrowUtils.throwIf(enumBySpaceLeave == null, ErrorCode.PARAMS_ERROR, "空间类型错误");
        }
        // 只有查询所有空间才有排行榜
        if(spaceUsageRankRequest.getIsAll() != null && spaceUsageRankRequest.getIsAll()){
            // 只有管理员可以查询
            ThrowUtils.throwIf(!userService.isAdmin(user), ErrorCode.NO_AUTH_ERROR);
        }else{
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 拼接查询条件
        QueryWrapper<Space> spaceQueryWrapper = new QueryWrapper<>();
        spaceQueryWrapper.select("id,spaceName,totalSize,totalCount,maxSize,maxCount")
                .eq(ObjectUtil.isNotEmpty(spaceLeave), "spaceLevel", spaceLeave)
                .orderByDesc("totalSize + totalCount")
                .last("limit " + spaceUsageRankRequest.getTop());
        List<Map<String, Object>> maps = spaceService.getBaseMapper()
                .selectMaps(spaceQueryWrapper);
       if(CollUtil.isEmpty(maps)){
          return null;
       }
        List<SpaceUsageRankResponse> collect = maps.stream()
                .map(map -> SpaceUsageRankResponse.builder()
                        .spaceId((Long) map.get("id"))
                        .spaceName((String) map.get("spaceName"))
                        .totalSize((Long) map.get("totalSize"))
                        .totalCount((Long) map.get("totalCount"))
                        .maxSize((Long) map.get("maxSize"))
                        .maxCount((Long) map.get("maxCount"))
                        .build())
                .collect(Collectors.toList());
        return collect;
    }

    /**
     * 拼接查询条件
     */
    public Space buildQueryWrapper(BaseSpaceStatisticsRequest spaceSizeUsageRequest, QueryWrapper<Picture> queryWrapper, User user) {
        // 查询私有空间
        if (spaceSizeUsageRequest.getSpaceId() != null && spaceSizeUsageRequest.getSpaceId() > 0) {
            Space space = spaceService.getById(spaceSizeUsageRequest.getSpaceId());
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "该空间不存在");
            // 只有私有空间本人和管理员可以查询
            if (!space.getUserId().equals(user.getId()) && !userService.isAdmin(user)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
            queryWrapper.eq("spaceId", spaceSizeUsageRequest.getSpaceId());
            return space;
        }
        // 查询公共空间
        else if (spaceSizeUsageRequest.getIsPublic() != null && spaceSizeUsageRequest.getIsPublic()) {
            // 只有管理员可查询
            if (!userService.isAdmin(user)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
            // 只查询spaceId为null的公共空间
            queryWrapper.isNull("spaceId");
        }
        // 查询所有空间
        else if (spaceSizeUsageRequest.getIsAll() != null && spaceSizeUsageRequest.getIsAll()) {
            // 只有管理员可查询
            if (!userService.isAdmin(user)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
        } else {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return null;
    }
}
